home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / trace_ds.c < prev    next >
C/C++ Source or Header  |  2001-06-23  |  21KB  |  997 lines

  1. /*
  2.  * Copyright 1993, 1994, 1995, 1999, 2000 by Paul Mattes.
  3.  *  Permission to use, copy, modify, and distribute this software and its
  4.  *  documentation for any purpose and without fee is hereby granted,
  5.  *  provided that the above copyright notice appear in all copies and that
  6.  *  both that copyright notice and this permission notice appear in
  7.  *  supporting documentation.
  8.  */
  9.  
  10. /*
  11.  *    trace_ds.c
  12.  *        3270 data stream tracing.
  13.  *
  14.  */
  15.  
  16. #include "globals.h"
  17.  
  18. #if defined(X3270_TRACE) /*[*/
  19.  
  20. #if defined(X3270_DISPLAY) /*[*/
  21. #include <X11/StringDefs.h>
  22. #include <X11/Xaw/Dialog.h>
  23. #endif /*]*/
  24. #include <errno.h>
  25. #include <signal.h>
  26. #include <time.h>
  27. #include <stdarg.h>
  28. #include <fcntl.h>
  29. #include "3270ds.h"
  30. #include "appres.h"
  31. #include "objects.h"
  32. #include "resources.h"
  33. #include "ctlr.h"
  34.  
  35. #include "ctlrc.h"
  36. #include "menubarc.h"
  37. #include "popupsc.h"
  38. #include "printc.h"
  39. #include "savec.h"
  40. #include "tablesc.h"
  41. #include "telnetc.h"
  42. #include "trace_dsc.h"
  43. #include "utilc.h"
  44.  
  45. /* Statics */
  46. static int      dscnt = 0;
  47. static int      tracewindow_pid = -1;
  48.  
  49. /* Globals */
  50. FILE           *tracef = (FILE *) 0;
  51. struct timeval  ds_ts;
  52. Boolean         trace_skipping = False;
  53.  
  54. static const char *
  55. unknown(unsigned char value)
  56. {
  57.     static char buf[64];
  58.  
  59.     (void) sprintf(buf, "unknown[0x%x]", value);
  60.     return buf;
  61. }
  62.  
  63. /* display a (row,col) */
  64. const char *
  65. rcba(int baddr)
  66. {
  67.     static char buf[16];
  68.  
  69.     (void) sprintf(buf, "(%d,%d)", baddr/COLS + 1, baddr%COLS + 1);
  70.     return buf;
  71. }
  72.  
  73. const char *
  74. see_ebc(unsigned char ch)
  75. {
  76.     static char buf[8];
  77.  
  78.     switch (ch) {
  79.         case FCORDER_NULL:
  80.         return "NULL";
  81.         case FCORDER_SUB:
  82.         return "SUB";
  83.         case FCORDER_DUP:
  84.         return "DUP";
  85.         case FCORDER_FM:
  86.         return "FM";
  87.         case FCORDER_FF:
  88.         return "FF";
  89.         case FCORDER_CR:
  90.         return "CR";
  91.         case FCORDER_NL:
  92.         return "NL";
  93.         case FCORDER_EM:
  94.         return "EM";
  95.         case FCORDER_EO:
  96.         return "EO";
  97.     }
  98.     if (ebc2asc[ch])
  99.         (void) sprintf(buf, "%c", ebc2asc[ch]);
  100.     else
  101.         (void) sprintf(buf, "\\%o", ch);
  102.     return buf;
  103. }
  104.  
  105. const char *
  106. see_aid(unsigned char code)
  107. {
  108.     switch (code) {
  109.     case AID_NO: 
  110.         return "NoAID";
  111.     case AID_ENTER: 
  112.         return "Enter";
  113.     case AID_PF1: 
  114.         return "PF1";
  115.     case AID_PF2: 
  116.         return "PF2";
  117.     case AID_PF3: 
  118.         return "PF3";
  119.     case AID_PF4: 
  120.         return "PF4";
  121.     case AID_PF5: 
  122.         return "PF5";
  123.     case AID_PF6: 
  124.         return "PF6";
  125.     case AID_PF7: 
  126.         return "PF7";
  127.     case AID_PF8: 
  128.         return "PF8";
  129.     case AID_PF9: 
  130.         return "PF9";
  131.     case AID_PF10: 
  132.         return "PF10";
  133.     case AID_PF11: 
  134.         return "PF11";
  135.     case AID_PF12: 
  136.         return "PF12";
  137.     case AID_PF13: 
  138.         return "PF13";
  139.     case AID_PF14: 
  140.         return "PF14";
  141.     case AID_PF15: 
  142.         return "PF15";
  143.     case AID_PF16: 
  144.         return "PF16";
  145.     case AID_PF17: 
  146.         return "PF17";
  147.     case AID_PF18: 
  148.         return "PF18";
  149.     case AID_PF19: 
  150.         return "PF19";
  151.     case AID_PF20: 
  152.         return "PF20";
  153.     case AID_PF21: 
  154.         return "PF21";
  155.     case AID_PF22: 
  156.         return "PF22";
  157.     case AID_PF23: 
  158.         return "PF23";
  159.     case AID_PF24: 
  160.         return "PF24";
  161.     case AID_OICR: 
  162.         return "OICR";
  163.     case AID_MSR_MHS: 
  164.         return "MSR_MHS";
  165.     case AID_SELECT: 
  166.         return "Select";
  167.     case AID_PA1: 
  168.         return "PA1";
  169.     case AID_PA2: 
  170.         return "PA2";
  171.     case AID_PA3: 
  172.         return "PA3";
  173.     case AID_CLEAR: 
  174.         return "Clear";
  175.     case AID_SYSREQ: 
  176.         return "SysReq";
  177.     case AID_QREPLY:
  178.         return "QueryReplyAID";
  179.     default: 
  180.         return unknown(code);
  181.     }
  182. }
  183.  
  184. const char *
  185. see_attr(unsigned char fa)
  186. {
  187.     static char buf[256];
  188.     const char *paren = "(";
  189.  
  190.     buf[0] = '\0';
  191.  
  192.     if (fa & 0x04) {
  193.         (void) strcat(buf, paren);
  194.         (void) strcat(buf, "protected");
  195.         paren = ",";
  196.         if (fa & 0x08) {
  197.             (void) strcat(buf, paren);
  198.             (void) strcat(buf, "skip");
  199.             paren = ",";
  200.         }
  201.     } else if (fa & 0x08) {
  202.         (void) strcat(buf, paren);
  203.         (void) strcat(buf, "numeric");
  204.         paren = ",";
  205.     }
  206.     switch (fa & 0x03) {
  207.     case 0:
  208.         break;
  209.     case 1:
  210.         (void) strcat(buf, paren);
  211.         (void) strcat(buf, "detectable");
  212.         paren = ",";
  213.         break;
  214.     case 2:
  215.         (void) strcat(buf, paren);
  216.         (void) strcat(buf, "intensified");
  217.         paren = ",";
  218.         break;
  219.     case 3:
  220.         (void) strcat(buf, paren);
  221.         (void) strcat(buf, "nondisplay");
  222.         paren = ",";
  223.         break;
  224.     }
  225.     if (fa & 0x20) {
  226.         (void) strcat(buf, paren);
  227.         (void) strcat(buf, "modified");
  228.         paren = ",";
  229.     }
  230.     if (strcmp(paren, "("))
  231.         (void) strcat(buf, ")");
  232.     else
  233.         (void) strcpy(buf, "(default)");
  234.  
  235.     return buf;
  236. }
  237.  
  238. static const char *
  239. see_highlight(unsigned char setting)
  240. {
  241.     switch (setting) {
  242.         case XAH_DEFAULT:
  243.         return "default";
  244.         case XAH_NORMAL:
  245.         return "normal";
  246.         case XAH_BLINK:
  247.         return "blink";
  248.         case XAH_REVERSE:
  249.         return "reverse";
  250.         case XAH_UNDERSCORE:
  251.         return "underscore";
  252.         case XAH_INTENSIFY:
  253.         return "intensify";
  254.         default:
  255.         return unknown(setting);
  256.     }
  257. }
  258.  
  259. #if !defined(X3270_DISPLAY) /*[*/
  260. static
  261. #endif /*]*/
  262. const char *
  263. see_color(unsigned char setting)
  264. {
  265.     static const char *color_name[] = {
  266.         "neutralBlack",
  267.         "blue",
  268.         "red",
  269.         "pink",
  270.         "green",
  271.         "turquoise",
  272.         "yellow",
  273.         "neutralWhite",
  274.         "black",
  275.         "deepBlue",
  276.         "orange",
  277.         "purple",
  278.         "paleGreen",
  279.         "paleTurquoise",
  280.         "grey",
  281.         "white"
  282.     };
  283.  
  284.     if (setting == XAC_DEFAULT)
  285.         return "default";
  286.     else if (setting < 0xf0 || setting > 0xff)
  287.         return unknown(setting);
  288.     else
  289.         return color_name[setting - 0xf0];
  290. }
  291.  
  292. static const char *
  293. see_transparency(unsigned char setting)
  294. {
  295.     switch (setting) {
  296.         case XAT_DEFAULT:
  297.         return "default";
  298.         case XAT_OR:
  299.         return "or";
  300.         case XAT_XOR:
  301.         return "xor";
  302.         case XAT_OPAQUE:
  303.         return "opaque";
  304.         default:
  305.         return unknown(setting);
  306.     }
  307. }
  308.  
  309. static const char *
  310. see_validation(unsigned char setting)
  311. {
  312.     static char buf[64];
  313.     const char *paren = "(";
  314.  
  315.     (void) strcpy(buf, "");
  316.     if (setting & XAV_FILL) {
  317.         (void) strcat(buf, paren);
  318.         (void) strcat(buf, "fill");
  319.         paren = ",";
  320.     }
  321.     if (setting & XAV_ENTRY) {
  322.         (void) strcat(buf, paren);
  323.         (void) strcat(buf, "entry");
  324.         paren = ",";
  325.     }
  326.     if (setting & XAV_TRIGGER) {
  327.         (void) strcat(buf, paren);
  328.         (void) strcat(buf, "trigger");
  329.         paren = ",";
  330.     }
  331.     if (strcmp(paren, "("))
  332.         (void) strcat(buf, ")");
  333.     else
  334.         (void) strcpy(buf, "(none)");
  335.     return buf;
  336. }
  337.  
  338. static const char *
  339. see_outline(unsigned char setting)
  340. {
  341.     static char buf[64];
  342.     const char *paren = "(";
  343.  
  344.     (void) strcpy(buf, "");
  345.     if (setting & XAO_UNDERLINE) {
  346.         (void) strcat(buf, paren);
  347.         (void) strcat(buf, "underline");
  348.         paren = ",";
  349.     }
  350.     if (setting & XAO_RIGHT) {
  351.         (void) strcat(buf, paren);
  352.         (void) strcat(buf, "right");
  353.         paren = ",";
  354.     }
  355.     if (setting & XAO_OVERLINE) {
  356.         (void) strcat(buf, paren);
  357.         (void) strcat(buf, "overline");
  358.         paren = ",";
  359.     }
  360.     if (setting & XAO_LEFT) {
  361.         (void) strcat(buf, paren);
  362.         (void) strcat(buf, "left");
  363.         paren = ",";
  364.     }
  365.     if (strcmp(paren, "("))
  366.         (void) strcat(buf, ")");
  367.     else
  368.         (void) strcpy(buf, "(none)");
  369.     return buf;
  370. }
  371.  
  372. const char *
  373. see_efa(unsigned char efa, unsigned char value)
  374. {
  375.     static char buf[64];
  376.  
  377.     switch (efa) {
  378.         case XA_ALL:
  379.         (void) sprintf(buf, " all(%x)", value);
  380.         break;
  381.         case XA_3270:
  382.         (void) sprintf(buf, " 3270%s", see_attr(value));
  383.         break;
  384.         case XA_VALIDATION:
  385.         (void) sprintf(buf, " validation%s", see_validation(value));
  386.         break;
  387.         case XA_OUTLINING:
  388.         (void) sprintf(buf, " outlining(%s)", see_outline(value));
  389.         break;
  390.         case XA_HIGHLIGHTING:
  391.         (void) sprintf(buf, " highlighting(%s)", see_highlight(value));
  392.         break;
  393.         case XA_FOREGROUND:
  394.         (void) sprintf(buf, " foreground(%s)", see_color(value));
  395.         break;
  396.         case XA_CHARSET:
  397.         (void) sprintf(buf, " charset(%x)", value);
  398.         break;
  399.         case XA_BACKGROUND:
  400.         (void) sprintf(buf, " background(%s)", see_color(value));
  401.         break;
  402.         case XA_TRANSPARENCY:
  403.         (void) sprintf(buf, " transparency(%s)", see_transparency(value));
  404.         break;
  405.         default:
  406.         (void) sprintf(buf, " %s[0x%x]", unknown(efa), value);
  407.     }
  408.     return buf;
  409. }
  410.  
  411. const char *
  412. see_efa_only(unsigned char efa)
  413. {
  414.     switch (efa) {
  415.         case XA_ALL:
  416.         return "all";
  417.         case XA_3270:
  418.         return "3270";
  419.         case XA_VALIDATION:
  420.         return "validation";
  421.         case XA_OUTLINING:
  422.         return "outlining";
  423.         case XA_HIGHLIGHTING:
  424.         return "highlighting";
  425.         case XA_FOREGROUND:
  426.         return "foreground";
  427.         case XA_CHARSET:
  428.         return "charset";
  429.         case XA_BACKGROUND:
  430.         return "background";
  431.         case XA_TRANSPARENCY:
  432.         return "transparency";
  433.         default:
  434.         return unknown(efa);
  435.     }
  436. }
  437.  
  438. const char *
  439. see_qcode(unsigned char id)
  440. {
  441.     static char buf[64];
  442.  
  443.     switch (id) {
  444.         case QR_CHARSETS:
  445.         return "CharacterSets";
  446.         case QR_IMP_PART:
  447.         return "ImplicitPartition";
  448.         case QR_SUMMARY:
  449.         return "Summary";
  450.         case QR_USABLE_AREA:
  451.         return "UsableArea";
  452.         case QR_COLOR:
  453.         return "Color";
  454.         case QR_HIGHLIGHTING:
  455.         return "Highlighting";
  456.         case QR_REPLY_MODES:
  457.         return "ReplyModes";
  458.         case QR_ALPHA_PART:
  459.         return "AlphanumericPartitions";
  460.         case QR_DDM:
  461.         return "DistributedDataManagement";
  462.         default:
  463.         (void) sprintf(buf, "unknown[0x%x]", id);
  464.         return buf;
  465.     }
  466. }
  467.  
  468. /* Data Stream trace print, handles line wraps */
  469.  
  470. static char *tdsbuf = CN;
  471. #define TDS_LEN    75
  472.  
  473. static void
  474. trace_ds_s(char *s)
  475. {
  476.     int len = strlen(s);
  477.     Boolean nl = False;
  478.  
  479.     if (!toggled(DS_TRACE) || !len)
  480.         return;
  481.  
  482.     if (s && s[len-1] == '\n') {
  483.         len--;
  484.         nl = True;
  485.     }
  486.     while (dscnt + len >= 75) {
  487.         int plen = 75-dscnt;
  488.  
  489.         (void) fprintf(tracef, "%.*s ...\n... ", plen, s);
  490.         dscnt = 4;
  491.         s += plen;
  492.         len -= plen;
  493.     }
  494.     if (len) {
  495.         (void) fprintf(tracef, "%.*s", len, s);
  496.         dscnt += len;
  497.     }
  498.     if (nl) {
  499.         (void) fprintf(tracef, "\n");
  500.         dscnt = 0;
  501.     }
  502. }
  503.  
  504. void
  505. trace_ds(const char *fmt, ...)
  506. {
  507.     va_list args;
  508.  
  509.     va_start(args, fmt);
  510.  
  511.     /* allocate buffer */
  512.     if (tdsbuf == CN)
  513.         tdsbuf = Malloc(4096);
  514.  
  515.     /* print out remainder of message */
  516.     (void) vsprintf(tdsbuf, fmt, args);
  517.     trace_ds_s(tdsbuf);
  518.     va_end(args);
  519. }
  520.  
  521. /* Conditional event trace. */
  522. void
  523. trace_event(const char *fmt, ...)
  524. {
  525.     va_list args;
  526.  
  527.     if (!toggled(EVENT_TRACE) || tracef == (FILE *)NULL)
  528.         return;
  529.  
  530.     va_start(args, fmt);
  531.  
  532.     /* print out message */
  533.     (void) vfprintf(tracef, fmt, args);
  534.     va_end(args);
  535. }
  536.  
  537. #if defined(X3270_DISPLAY) /*[*/
  538. static Widget trace_shell = (Widget)NULL;
  539. #endif
  540. static int trace_reason;
  541.  
  542. /* Callback for "OK" button on trace popup */
  543. static void
  544. tracefile_callback(Widget w, XtPointer client_data, XtPointer call_data unused)
  545. {
  546.     char *tfn;
  547.     char *tracecmd;
  548.     char *full_cmd;
  549.     time_t clk;
  550.     Boolean piped = False;
  551.     int pipefd[2];
  552.  
  553. #if defined(X3270_DISPLAY) /*[*/
  554.     if (w)
  555.         tfn = XawDialogGetValueString((Widget)client_data);
  556.     else
  557. #endif /*]*/
  558.         tfn = (char *)client_data;
  559.     tfn = do_subst(tfn, True, True);
  560.     if (strchr(tfn, '\'') ||
  561.         ((int)strlen(tfn) > 0 && tfn[strlen(tfn)-1] == '\\')) {
  562.         popup_an_error("Illegal file name: %s\n", tfn);
  563.         Free(tfn);
  564.         return;
  565.     }
  566.     if (!strcmp(tfn, "stdout")) {
  567.         tracef = stdout;
  568.     } else if (!strcmp(tfn, "none") || !tfn[0]) {
  569.  
  570. #ifndef AMIGA
  571.         if (pipe(pipefd) < 0) {
  572. #else
  573.         if (1) {
  574. #endif
  575.             popup_an_errno(errno, "pipe() failed");
  576.             Free(tfn);
  577.             return;
  578.         }
  579.         tracef = fdopen(pipefd[1], "w");
  580.         if (tracef == (FILE *)NULL) {
  581.             popup_an_errno(errno, "fdopen() failed");
  582.             Free(tfn);
  583.             return;
  584.         }
  585.         (void) SETLINEBUF(tracef);
  586.         (void) fcntl(pipefd[1], F_SETFD, 1);
  587.         piped = True;
  588.     } else {
  589.         tracef = fopen(tfn, "a");
  590.         if (tracef == (FILE *)NULL) {
  591.             popup_an_errno(errno, tfn);
  592.             Free(tfn);
  593.             return;
  594.         }
  595.         (void) SETLINEBUF(tracef);
  596.         (void) fcntl(fileno(tracef), F_SETFD, 1);
  597.     }
  598.  
  599.     /* Start the monitor window */
  600.     tracecmd = get_resource(ResTraceCommand);
  601.     if (tracecmd == CN || !strcmp(tracecmd, "none") || tracef == stdout)
  602.         goto done;
  603. #ifndef AMIGA
  604.     switch (tracewindow_pid = fork()) {
  605.         case 0:    /* child process */
  606.         if (piped) {
  607.             char cmd[64];
  608.  
  609.             (void) sprintf(cmd, "cat /dev/fd/%d", pipefd[0]);
  610.             (void) execlp("xterm", "xterm", "-title", "trace",
  611.                 "-sb", "-e", "/bin/sh", "-c", cmd, CN);
  612.         } else {
  613.             full_cmd = xs_buffer("%s <'%s'", tracecmd, tfn);
  614.             (void) execlp("xterm", "xterm", "-title", tfn,
  615.                 "-sb", "-e", "/bin/sh", "-c", full_cmd, CN);
  616.         }
  617.         (void) perror("exec(xterm)");
  618.         _exit(1);
  619.         default:    /* parent */
  620.         if (piped)
  621.             (void) close(pipefd[0]);
  622.         ++children;
  623.         break;
  624.         case -1:    /* error */
  625.         popup_an_errno(errno, "fork()");
  626.         break;
  627.     }
  628. #endif
  629.     done:
  630.     Free(tfn);
  631.  
  632.     /* Display current status */
  633.     clk = time((time_t *)0);
  634.     (void) fprintf(tracef, "Trace started %s", ctime(&clk));
  635.     (void) fprintf(tracef, " Version: %s\n", build);
  636.     save_yourself();
  637.     (void) fprintf(tracef, " Command: %s\n", command_string);
  638.     (void) fprintf(tracef, " Model %s", model_name);
  639.     (void) fprintf(tracef, ", %s display", 
  640.         appres.mono ? "monochrome" : "color");
  641.     if (appres.extended)
  642.         (void) fprintf(tracef, ", extended data stream");
  643.     if (!appres.mono)
  644.         (void) fprintf(tracef, ", %scolor",
  645.             appres.m3279 ? "full " : "pseudo-");
  646.     if (appres.charset)
  647.         (void) fprintf(tracef, ", %s charset", appres.charset);
  648.     if (appres.apl_mode)
  649.         (void) fprintf(tracef, ", APL mode");
  650.     (void) fprintf(tracef, "\n");
  651.     if (CONNECTED)
  652.         (void) fprintf(tracef, " Connected to %s, port %u\n",
  653.             current_host, current_port);
  654.  
  655.  
  656.     /* We're really tracing, turn the flag on. */
  657.     appres.toggle[trace_reason].value = True;
  658.     appres.toggle[trace_reason].changed = True;
  659.     menubar_retoggle(&appres.toggle[trace_reason]);
  660.  
  661. #if defined(X3270_DISPLAY) /*[*/
  662.     if (w)
  663.         XtPopdown(trace_shell);
  664. #endif /*]*/
  665.  
  666.     /* Snap the current TELNET options. */
  667.     if (net_snap_options()) {
  668.         (void) fprintf(tracef, " TELNET state:\n");
  669.         trace_netdata('<', obuf, obptr - obuf);
  670.     }
  671.  
  672.     /* Dump the screen contents and modes into the trace file. */
  673.     if (CONNECTED) {
  674.         /*
  675.          * Note that if the screen is not formatted, we do not
  676.          * attempt to save what's on it.  However, if we're in
  677.          * 3270 SSCP-LU or NVT mode, we'll do a dummy, empty
  678.          * write to ensure that the display is in the right
  679.          * mode.
  680.          */
  681.         if (formatted) {
  682.             (void) fprintf(tracef, " Screen contents:\n");
  683.             obptr = obuf;
  684. #if defined(X3270_TN3270E) /*[*/
  685.             (void) net_add_dummy_tn3270e();
  686. #endif /*]*/
  687.             ctlr_snap_buffer();
  688.             space3270out(2);
  689.             net_add_eor(obuf, obptr - obuf);
  690.             obptr += 2;
  691.             trace_netdata('<', obuf, obptr - obuf);
  692.  
  693.             obptr = obuf;
  694. #if defined(X3270_TN3270E) /*[*/
  695.             (void) net_add_dummy_tn3270e();
  696. #endif /*]*/
  697.             if (ctlr_snap_modes()) {
  698.                 (void) fprintf(tracef, " 3270 modes:\n");
  699.                 space3270out(2);
  700.                 net_add_eor(obuf, obptr - obuf);
  701.                 obptr += 2;
  702.                 trace_netdata('<', obuf, obptr - obuf);
  703.             }
  704.         }
  705. #if defined(X3270_TN3270E) /*[*/
  706.         else if (IN_E) {
  707.             obptr = obuf;
  708.             if (net_add_dummy_tn3270e()) {
  709.                 (void) fprintf(tracef,
  710.                     " Screen contents:\n");
  711.                 space3270out(2);
  712.                 net_add_eor(obuf, obptr - obuf);
  713.                 obptr += 2;
  714.                 trace_netdata('<', obuf, obptr - obuf);
  715.             }
  716.         }
  717. #endif /*]*/
  718.     }
  719.  
  720.     (void) fprintf(tracef, " Data stream:\n");
  721. }
  722.  
  723. #if defined(X3270_DISPLAY) /*[*/
  724. /* Callback for "No File" button on trace popup */
  725. static void
  726. no_tracefile_callback(Widget w, XtPointer client_data,
  727.     XtPointer call_data unused)
  728. {
  729.     tracefile_callback((Widget)NULL, "", PN);
  730.     XtPopdown(trace_shell);
  731. }
  732. #endif /*]*/
  733.  
  734. /* Open the trace file. */
  735. static void
  736. tracefile_on(int reason, enum toggle_type tt)
  737. {
  738.     char tracefile_buf[256];
  739.     char *tracefile;
  740.  
  741.     if (tracef)
  742.         return;
  743.  
  744.     trace_reason = reason;
  745.     if (appres.secure) {
  746.         tracefile_callback((Widget)NULL, "none", PN);
  747.         return;
  748.     }
  749.     if (appres.trace_file)
  750.         tracefile = appres.trace_file;
  751.     else {
  752.         (void) sprintf(tracefile_buf, "%s/x3trc.%d", appres.trace_dir,
  753.             getpid());
  754.         tracefile = tracefile_buf;
  755.     }
  756.  
  757. #if defined(X3270_DISPLAY) /*[*/
  758.     if (tt == TT_INITIAL)
  759. #endif /*]*/
  760.     {
  761.         tracefile_callback((Widget)NULL, tracefile, PN);
  762.         return;
  763.     }
  764. #if defined(X3270_DISPLAY) /*[*/
  765.     if (trace_shell == NULL) {
  766.         trace_shell = create_form_popup("trace",
  767.             tracefile_callback, no_tracefile_callback, FORM_NO_WHITE);
  768.         XtVaSetValues(XtNameToWidget(trace_shell, ObjDialog),
  769.             XtNvalue, tracefile,
  770.             NULL);
  771.     }
  772.  
  773.     /* Turn the toggle _off_ until the popup succeeds. */
  774.     appres.toggle[reason].value = False;
  775.     appres.toggle[reason].changed = True;
  776.  
  777.     popup_popup(trace_shell, XtGrabExclusive);
  778. #endif /*]*/
  779. }
  780.  
  781. /* Close the trace file. */
  782. static void
  783. tracefile_off(void)
  784. {
  785.     time_t clk;
  786.  
  787.     clk = time((time_t *)0);
  788.     (void) fprintf(tracef, "Trace stopped %s", ctime(&clk));
  789.     if (tracewindow_pid != -1)
  790. #ifndef AMIGA
  791.         (void) kill(tracewindow_pid, SIGKILL);
  792. #else
  793. ;/*        (void) kill(tracewindow_pid, SIGTERM);*/
  794. #endif
  795.     tracewindow_pid = -1;
  796.     if (tracef != stdout)
  797.         (void) fclose(tracef);
  798.     tracef = (FILE *) NULL;
  799. }
  800.  
  801. void
  802. toggle_dsTrace(struct toggle *t unused, enum toggle_type tt)
  803. {
  804.     /* If turning on trace and no trace file, open one. */
  805.     if (toggled(DS_TRACE) && !tracef)
  806.         tracefile_on(DS_TRACE, tt);
  807.  
  808.     /* If turning off trace and not still tracing events, close the
  809.        trace file. */
  810.     else if (!toggled(DS_TRACE) && !toggled(EVENT_TRACE))
  811.         tracefile_off();
  812.  
  813.     if (toggled(DS_TRACE))
  814.         (void) gettimeofday(&ds_ts, (struct timezone *)NULL);
  815. }
  816.  
  817. void
  818. toggle_eventTrace(struct toggle *t unused, enum toggle_type tt)
  819. {
  820.     /* If turning on event debug, and no trace file, open one. */
  821.     if (toggled(EVENT_TRACE) && !tracef)
  822.         tracefile_on(EVENT_TRACE, tt);
  823.  
  824.     /* If turning off event debug, and not tracing the data stream,
  825.        close the trace file. */
  826.     else if (!toggled(EVENT_TRACE) && !toggled(DS_TRACE))
  827.         tracefile_off();
  828. }
  829.  
  830. /* Screen trace file support. */
  831.  
  832. #if defined(X3270_DISPLAY) /*[*/
  833. static Widget screentrace_shell = (Widget)NULL;
  834. #endif /*]*/
  835. static FILE *screentracef = (FILE *)0;
  836.  
  837. /*
  838.  * Screen trace function, called when the host clears the screen.
  839.  */
  840. static void
  841. do_screentrace(void)
  842. {
  843.     register int i;
  844.  
  845.     if (fprint_screen(screentracef, False)) {
  846.         for (i = 0; i < COLS; i++)
  847.             (void) fputc('=', screentracef);
  848.         (void) fputc('\n', screentracef);
  849.     }
  850. }
  851.  
  852. void
  853. trace_screen(void)
  854. {
  855.     trace_skipping = False;
  856.  
  857.     if (!toggled(SCREEN_TRACE) || !screentracef)
  858.         return;
  859.     do_screentrace();
  860. }
  861.  
  862. /* Called from ANSI emulation code to log a single character. */
  863. void
  864. trace_char(char c)
  865. {
  866.     if (!toggled(SCREEN_TRACE) || !screentracef)
  867.         return;
  868.     (void) fputc(c, screentracef);
  869. }
  870.  
  871. /*
  872.  * Called when disconnecting in ANSI mode, to finish off the trace file
  873.  * and keep the next screen clear from re-recording the screen image.
  874.  * (In a gross violation of data hiding and modularity, trace_skipping is
  875.  * manipulated directly in ctlr_clear()).
  876.  */
  877. void
  878. trace_ansi_disc(void)
  879. {
  880.     int i;
  881.  
  882.     (void) fputc('\n', screentracef);
  883.     for (i = 0; i < COLS; i++)
  884.         (void) fputc('=', screentracef);
  885.     (void) fputc('\n', screentracef);
  886.  
  887.     trace_skipping = True;
  888. }
  889.  
  890. /*
  891.  * Screen tracing callback.
  892.  * Returns True for success, False for failure.
  893.  */
  894. static Boolean
  895. screentrace_cb(char *tfn)
  896. {
  897.     tfn = do_subst(tfn, True, True);
  898.     screentracef = fopen(tfn, "a");
  899.     if (screentracef == (FILE *)NULL) {
  900.         popup_an_errno(errno, tfn);
  901.         Free(tfn);
  902.         return False;
  903.     }
  904.     Free(tfn);
  905.     (void) SETLINEBUF(screentracef);
  906.     (void) fcntl(fileno(screentracef), F_SETFD, 1);
  907.  
  908.     /* We're really tracing, turn the flag on. */
  909.     appres.toggle[SCREEN_TRACE].value = True;
  910.     appres.toggle[SCREEN_TRACE].changed = True;
  911.     menubar_retoggle(&appres.toggle[SCREEN_TRACE]);
  912.     return True;
  913. }
  914.  
  915. #if defined(X3270_DISPLAY) /*[*/
  916. /* Callback for "OK" button on screentrace popup */
  917. static void
  918. screentrace_callback(Widget w unused, XtPointer client_data,
  919.     XtPointer call_data unused)
  920. {
  921.     if (screentrace_cb(XawDialogGetValueString((Widget)client_data)))
  922.         XtPopdown(screentrace_shell);
  923. }
  924.  
  925. /* Callback for second "OK" button on screentrace popup */
  926. static void
  927. onescreen_callback(Widget w, XtPointer client_data, XtPointer call_data unused)
  928. {
  929.     char *tfn;
  930.  
  931.     if (w)
  932.         tfn = XawDialogGetValueString((Widget)client_data);
  933.     else
  934.         tfn = (char *)client_data;
  935.     tfn = do_subst(tfn, True, True);
  936.     screentracef = fopen(tfn, "a");
  937.     if (screentracef == (FILE *)NULL) {
  938.         popup_an_errno(errno, tfn);
  939.         XtFree(tfn);
  940.         return;
  941.     }
  942.     (void) fcntl(fileno(screentracef), F_SETFD, 1);
  943.     XtFree(tfn);
  944.  
  945.     /* Save the current image, once. */
  946.     do_screentrace();
  947.  
  948.     /* Close the file, we're done. */
  949.     (void) fclose(screentracef);
  950.     screentracef = (FILE *)NULL;
  951.  
  952.     if (w)
  953.         XtPopdown(screentrace_shell);
  954. }
  955. #endif /*]*/
  956.  
  957. void
  958. toggle_screenTrace(struct toggle *t unused, enum toggle_type tt)
  959. {
  960.     char tracefile_buf[256];
  961.     char *tracefile;
  962.  
  963.     if (toggled(SCREEN_TRACE)) {
  964.         if (appres.screentrace_file)
  965.             tracefile = appres.screentrace_file;
  966.         else {
  967.             (void) sprintf(tracefile_buf, "%s/x3scr.%d",
  968.                 appres.trace_dir, getpid());
  969.             tracefile = tracefile_buf;
  970.         }
  971.         if (tt == TT_INITIAL) {
  972.             (void) screentrace_cb(NewString(tracefile));
  973.             return;
  974.         }
  975. #if defined(X3270_DISPLAY) /*[*/
  976.         if (screentrace_shell == NULL) {
  977.             screentrace_shell = create_form_popup("screentrace",
  978.                 screentrace_callback, onescreen_callback,
  979.                 FORM_NO_WHITE);
  980.             XtVaSetValues(XtNameToWidget(screentrace_shell,
  981.                     ObjDialog),
  982.                 XtNvalue, tracefile,
  983.                 NULL);
  984.         }
  985.         appres.toggle[SCREEN_TRACE].value = False;
  986.         appres.toggle[SCREEN_TRACE].changed = True;
  987.         popup_popup(screentrace_shell, XtGrabExclusive);
  988. #endif /*]*/
  989.     } else {
  990.         if (ctlr_any_data() && !trace_skipping)
  991.             do_screentrace();
  992.         (void) fclose(screentracef);
  993.     }
  994. }
  995.  
  996. #endif /*]*/
  997.